package com.example.demo02;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.SpringServletContainerInitializer;
import org.springframework.web.WebApplicationInitializer;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;

/**
 * 启动原理:
 * Servlet 3.0 规范规定:
 * 1. 服务器启动，会扫描所有 jar 包中 META-INF/services/javax.servlet.ServletContainerlnitializer 目录文件中
 * 配置的 {@link ServletContainerInitializer} 类，然后调用其 {onStartup} 方法。
 * 2. 还可以使用 @HandlesTypes，在应用启动的时候加载我们感兴趣的类。
 * <p>
 * 探索启动原理:
 * 1. 我们在 org\springframework\spring-web\5.2.8.RELEASE\spring-web-5.2.8.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer 中
 * 发现配置了 {@link SpringServletContainerInitializer}，此类实现了 {@link ServletContainerInitializer} 接口，那么在服务器启动的时候会调用其 {onStartup}
 * 方法;
 * 2. 并且在 {@link SpringServletContainerInitializer} 上标注了 @HandlesTypes(WebApplicationInitializer.class) 注解，那么在调用 {onStartup} 方法时，
 * 会将 {@link WebApplicationInitializer} 类型的对象作为 {onStartup} 方法的参数传进去，而我们 {@link ServletInitializer} 类继承 SpringBootServletInitializer，
 * SpringBootServletInitializer 实现了 {@link WebApplicationInitializer}。所以我们的 {@link ServletInitializer} 也就是 {@link SpringServletContainerInitializer}
 * 感兴趣的类。
 * 3. {@link SpringServletContainerInitializer#onStartup} 方法其实就是循环遍历调用我们感兴趣的 {@link WebApplicationInitializer#onStartup(ServletContext)}
 */
public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Demo02Application.class);
    }

}
